package com.lz.utils;

import io.jsonwebtoken.Jwts; // 导入jjwt库提供的主要类，用于创建和解析JWT
import io.jsonwebtoken.SignatureAlgorithm; // 导入签名算法接口
import io.jsonwebtoken.Claims; // 导入Claims接口，代表JWT的声明集合
import io.jsonwebtoken.JwtException; // 导入JwtException，用于处理JWT相关异常
import java.util.Date; // 导入Java的日期类
import java.util.function.Function; // 导入Function接口，用于传递一个函数作为参数

public class JwtUtil {
    private static final String SECRET_KEY = "your-secret-key"; // 设置JWT的密钥，应该设置为一个安全且随机的值

    // 生成JWT的方法
    public static String createToken(String subject) {
        return Jwts.builder()
                .setSubject(subject) // 设置JWT的主题，通常是用户ID或用户名
                .setIssuedAt(new Date()) // 设置JWT的签发时间
                .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 设置JWT的过期时间，这里设置为10小时后
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY) // 使用HMAC SHA-256算法和前面定义的密钥签名JWT
                .compact(); // 生成并返回JWT字符串
    }

    // 从JWT中提取主题的方法
    public static String getSubjectFromToken(String token) {
        return extractClaim(token, Claims::getSubject); // 使用extractClaim方法提取主题
    }

    // 从JWT中提取签发时间的方法
    public static Date getIssuedAtDateFromToken(String token) {
        return extractClaim(token, Claims::getIssuedAt); // 使用extractClaim方法提取签发时间
    }

    // 从JWT中提取过期时间的方法
    public static Date getExpirationDateFromToken(String token) {
        return extractClaim(token, Claims::getExpiration); // 使用extractClaim方法提取过期时间
    }

    // 私有辅助方法，用于从JWT中提取声明
    private static <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token); // 先提取所有声明
        return claimsResolver.apply(claims); // 应用提供的Function来获取需要的声明
    }

    // 私有方法，用于解析JWT并提取所有声明
    public static Claims extractAllClaims(String token) {
        try {
            return Jwts.parser()
                    .setSigningKey(SECRET_KEY) // 设置用于验证签名的密钥
                    .parseClaimsJws(token) // 解析JWT
                    .getBody(); // 获取Claims对象
        } catch (JwtException | IllegalArgumentException e) {
            throw new IllegalStateException("Token is invalid: " + e.getMessage(), e); // 如果JWT无效，抛出异常
        }
    }

    // 检查JWT是否过期的方法
    public static boolean isTokenExpired(String token) {
        return extractClaim(token, Claims::getExpiration).before(new Date()); // 提取过期时间并与当前时间比较
    }

    // 验证JWT的方法，检查JWT是否有效并且属于指定用户
    public static boolean validateToken(String token, String user) {
        final String subject = getSubjectFromToken(token); // 获取JWT的主题
        return !isTokenExpired(token) && subject.equals(user); // 检查JWT未过期且主题匹配用户
    }
}